const PromoteAccountSchema = require('../entity/promote/promoteaccount');
const PromoteRecordSchema = require('../entity/promote/promoterecord');
const PromoteIncomeSchema = require('../entity/promote/promoteincome');
const PromoteConsumeSchema = require('../entity/promote/promoteconsume');
const EnvelopeSchema = require('../entity/promote/envelope');
const UserBaseSchema = require('../entity/user/userbase');

const globalConfigService = require('./globalConfigService');
const wxQrcode = require('./weixin/qrcode');
const moment = require('moment');

const { getCurrentTimestamp } = require('../module/tool/time');
const { CommonServiceError } = require('../module/error/svcerror');

const PromoteType = require('../module/const/PromoteType');
const OrderStatus = require('../module/const/OrderStatus');
const EnvelopeStatus = require('../module/const/EnvelopeStatus');
const ConsumerStatus = require('../module/const/ConsumerStatus');

// =========================== 红包 ===============================
// 【发送】新用户红包
async function dispatchEnvelope (userId) {
    const envelopeEntity = new EnvelopeSchema();
    const envelopeModel = envelopeEntity.getModel();

    // 用户没发过红包，则发送红包
    if (!await envelopeModel.exists({ userId })) {
        const userBaseModel = new UserBaseSchema().getModel();
        const userInfo = await userBaseModel.findById(userId);

        const defaultEnvelopeConfig = await globalConfigService.getGlobalConfig('default_envelope_config');
        const count = defaultEnvelopeConfig.data.count;
        for (let i = 0; i < count; i++) {
            await envelopeEntity.getDoc({
                userId,
                reachAmount: defaultEnvelopeConfig.data.reachAmount,
                amount: defaultEnvelopeConfig.data.amount,
                status: EnvelopeStatus.enable,
                areaId: userInfo.authAreaId
            }).save();
        }
    }
    return 1;
}
// 【查询】红包信息
async function getEnvelopeById (envelopeId) {
    const envelopeModel = new EnvelopeSchema().getModel();
    return envelopeModel.findById(envelopeId);
}

// 【使用】红包，红包使用状态：[enable（可用）, used（已使用）, overdue（过期）]
async function useEnvelop (envelopId) {
    const envelopeModel = new EnvelopeSchema().getModel();
    const envelopeData = await envelopeModel.findById(envelopId);
    if (envelopeData.status !== EnvelopeStatus.enable) {
        throw new CommonServiceError('红包已失效！');
    }
    await envelopeModel.findByIdAndUpdate(envelopId, {
        status: EnvelopeStatus.used,
        useTime: getCurrentTimestamp()
    });
    return 1;
}
// 【恢复】红包
async function recoverEnvelop (envelopId) {
    const envelopeModel = new EnvelopeSchema().getModel();
    const envelopeData = await envelopeModel.findById(envelopId);
    if (!envelopeData) return;
    if (envelopeData.status !== EnvelopeStatus.used) {
        throw new CommonServiceError('红包未被使用！');
    }
    await envelopeModel.findByIdAndUpdate(envelopId, {
        status: EnvelopeStatus.enable,
        useTime: 0
    });
    return 1;
}

// --授权客户
async function authCustom (promoterId, customId) {
    const userBaseModel = new UserBaseSchema().getModel();
    await userBaseModel.findByIdAndUpdate(customId, { vip_id: '62600b6cb642542bfe9a609e' });
    return 1;
}

// =========================== 分销 ===============================
// 初始化用户推广账户
async function initPromoteAccount (userId) {
    const promoteAccountEntity = new PromoteAccountSchema();
    const promoteAccountModel = promoteAccountEntity.getModel();

    if (!await promoteAccountModel.exists({ userId })) {
        const defaultPromoteConfig = await globalConfigService.getGlobalConfig('default_promote_config');
        await promoteAccountEntity.getDoc({
            userId,
            promoteType: defaultPromoteConfig.data.promoteType,
            promoteValue: defaultPromoteConfig.data.promoteValue,
            coinCount: 0
        }).save();
    }
    return 1;
}
// 绑定推广关系（生成推广记录）
async function bindPromoteRelationship (promoterId, customId, areaId) {
    if (promoterId === customId) return;
    const promoteRecordEntity = new PromoteRecordSchema();
    const promoteRecordModel = promoteRecordEntity.getModel();

    const existRecord = await promoteRecordModel.exists({ customId });
    if (!existRecord) {
        await promoteRecordEntity.getDoc({ promoterId, customId, areaId }).save();
    }
    return 1;
}
// 查询我的推广二维码
async function getPromoteQrcode (userId) {
    const qrCode = await wxQrcode.generatePermanentMultiSceneQRCode('pages/index/index', userId);
    return { qrCode };
}

// =========================== 推广信息查询 ===============================
// 【收益总览】查询推广收益总览：今日预计收益，累计收益，推广人数，账户余额
async function getPromoteOverview (userId) {
    const currentTime = getCurrentTimestamp();
    // 今日预计收益（今日推广订单预计产生的收益）
    const timeBeginToday = moment().startOf('day').valueOf() / 1000;
    const todayIncome = await getPromoteIncomeAmount(userId, timeBeginToday, currentTime);
    // 累计收益
    const totalIncome = await getPromoteIncomeAmount(userId, 1, currentTime, OrderStatus.Finished.value);
    // 推广人数
    const promoteRecordModel = new PromoteRecordSchema().getModel();
    const promoteCount = await promoteRecordModel.countDocuments({ promoterId: userId });

    // 账户余额
    const accountData = await getPromoteAccountByUserId(userId);
    const coinCount = accountData.coinCount;
    return {
        todayIncome,
        totalIncome,
        promoteCount,
        coinCount
    };
}
// 【推广订单】查询我推广的订单信息：订单数量，订单列表，推广总金币数
async function getPromoteOrderInfo (promoterId, beginTime, endTime, offset, limit, status) {
    const amount = await getPromoteIncomeAmount(promoterId, beginTime, endTime, status);
    const orderInfo = await getPromoteIncomeRecord(promoterId, beginTime, endTime, offset, limit, status);
    orderInfo.amount = amount;
    return orderInfo;
}
// 【推广客户】查询推广客户记录
async function getPromoteRecord (promoterId, beginTime, endTime, offset, limit) {
    const query = { promoterId: PromoteRecordSchema.toObjectId(promoterId) };
    if (beginTime && endTime) {
        query.createTime = { $gte: parseInt(beginTime), $lte: parseInt(endTime) };
    }

    const promoteRecordModel = new PromoteRecordSchema().getModel();
    const count = await promoteRecordModel.countDocuments(query);
    const rows = await promoteRecordModel.aggregate([
        { $match: query },
        { $sort: { createTime: -1 } },
        { $skip: offset },
        { $limit: limit },
        {
            $lookup: {
                from: 'user_base',
                localField: 'customId',
                foreignField: '_id',
                as: 'userInfo'
            }
        },
        {
            $unwind: {
                path: '$userInfo',
                preserveNullAndEmptyArrays: true
            }
        }
    ]);
    return { count, rows };
}
// 查询推广【累计收入金币】
async function getPromoteIncomeAmount (promoterId, beginTime, endTime, status) {
    const query = {};
    if (promoterId) query.promoterId = PromoteIncomeSchema.toObjectId(promoterId);
    if (beginTime && endTime) {
        query.createTime = { $gte: parseInt(beginTime), $lte: parseInt(endTime) };
    }
    if (status !== undefined) query.status = status;

    const promoteIncomeModel = new PromoteIncomeSchema().getModel();
    const res = await promoteIncomeModel.aggregate([
        { $match: query },
        {
            $group: {
                _id: null,
                total: { $sum: '$promoteAmount' }
            }
        }
    ]);
    return res.length > 0 ? res[0].total : 0;
}
// 查询推广【订单记录】
async function getPromoteIncomeRecord (promoterId, beginTime, endTime, offset, limit, status) {
    const query = { promoterId: PromoteRecordSchema.toObjectId(promoterId) };
    if (beginTime && endTime) {
        query.createTime = { $gte: parseInt(beginTime), $lte: parseInt(endTime) };
    }
    if (status !== undefined) query.status = status;

    const promoteIncomeModel = new PromoteIncomeSchema().getModel();
    const count = await promoteIncomeModel.countDocuments(query);
    const rows = await promoteIncomeModel.aggregate([
        { $match: query },
        { $sort: { createTime: -1 } },
        { $skip: offset },
        { $limit: limit },
        {
            $lookup: {
                from: 'order',
                localField: 'orderId',
                foreignField: '_id',
                as: 'orderInfo'
            }
        },
        {
            $unwind: {
                path: '$orderInfo',
                preserveNullAndEmptyArrays: true
            }
        }
    ]);
    return { count, rows };
}

// 查询客户的推广员信息
async function getPromoteUserInfo (userId) {
    const promoteRecordModel = new PromoteRecordSchema().getModel();
    const promoteRecordData = await promoteRecordModel.findOne({ customId: userId });

    if (promoteRecordData) {
        const userBaseModel = new UserBaseSchema().getModel();
        const userInfo = await userBaseModel.findById(promoteRecordData.promoterId);
        return {
            userInfo: userInfo.toString(),
            isExist: true
        };
    } else {
        return { isExist: false };
    }
}
// 修改客户的业务员
async function changePromote (promoterId, customId) {
    const promoteRecordModel = new PromoteRecordSchema().getModel();
    const recordData = await promoteRecordModel.findOne({ customId: customId });
    if (recordData) {
        recordData.promoterId = promoterId;
        recordData.save();
    }
    return 1;
}

// =========================== 推广收支 ===============================
// 【提交】生成推广收益，推广收益状态：[Committed（已提交）,Cancel（已取消）,Finished（已结算）]，单位：元
async function generatePromoteIncome (orderId, price, customId, areaId) {
    const promoteIncomeEntity = new PromoteIncomeSchema();
    const promoteIncomeModel = promoteIncomeEntity.getModel();
    // 一个订单只会生成一个推广收入
    if (!await promoteIncomeModel.exists({ orderId })) {
        // 查询分销绑定关系
        const promoteRecordModel = new PromoteRecordSchema().getModel();
        const promoteRecordData = await promoteRecordModel.findOne({ customId });
        if (promoteRecordData) {
            // 查询推广员的推广账户
            const promoterId = promoteRecordData.promoterId;
            const promoterAccount = await getPromoteAccountByUserId(promoterId);
            const promoteType = promoterAccount.promoteType;
            const promoteValue = promoterAccount.promoteValue;
            const status = OrderStatus.Committed.value;
            // 确定抽成数额（固定数额或者百分比抽成）
            let promoteAmount;
            if (promoteType === PromoteType.fixed) {
                promoteAmount = promoteValue;
            } else if (promoteType === PromoteType.rate) {
                promoteAmount = (price / 100) * (promoteValue / 100);
            }

            await promoteIncomeEntity.getDoc({
                orderId,
                price,
                promoteType,
                promoteValue,
                promoteAmount,
                status,
                promoterId,
                customId,
                areaId
            }).save();
        }
    }
}
// 【取消】撤销推广收益
async function recoverPromoteRecord (orderId) {
    const promoteIncomeModel = new PromoteIncomeSchema().getModel();
    await promoteIncomeModel.findOneAndUpdate({ orderId }, { status: OrderStatus.Cancel.value });
    return 1;
}
// 【结算】分销收入，增加金币数量
async function settlementPromoteIncome (orderId) {
    const promoteIncomeModel = new PromoteIncomeSchema().getModel();
    const promoteIncomeData = await promoteIncomeModel.findOne({ orderId });

    if (promoteIncomeData) {
        if (promoteIncomeData.status === OrderStatus.Committed.value) {
            // 修改推广收入为已入账状态
            const time = Math.round(new Date().getTime() / 1000);
            promoteIncomeData.status = OrderStatus.Finished.value;
            promoteIncomeData.settlementTime = time;
            await promoteIncomeData.save();

            // 增加账户金币
            const promoteAccountModel = new PromoteAccountSchema().getModel();
            await promoteAccountModel.findOneAndUpdate({ userId: promoteIncomeData.promoterId }, { $inc: { coinCount: promoteIncomeData.promoteAmount } });
        }
    }
    return 1;
}

// 【消费】金币，消费类型：[order（下单抵扣）, withdraw（金币提现）]
async function consumeCoin (userId, orderId, coinCount, consumerType, areaId) {
    // 查询账户信息
    const promoteAccountModel = new PromoteAccountSchema().getModel();
    const accountInfo = await promoteAccountModel.findOne({ userId });

    if (accountInfo.coinCount < coinCount) {
        throw new CommonServiceError('金币不足！');
    }

    // 扣除金币
    await promoteAccountModel.findOneAndUpdate({ userId }, { $inc: { coinCount: -coinCount } });

    // 生成消费记录
    const promoteConsumeEntity = new PromoteConsumeSchema();
    await promoteConsumeEntity.getDoc({
        userId,
        orderId,
        consumerCount: coinCount,
        consumerType,
        areaId
    }).save();

    return 1;
}
// 【恢复】订单金币，消费记录状态：[normal（正常）, undo（撤销）]
async function recoverCoin (orderId) {
    // 查询消费记录
    const promoteConsumeModel = new PromoteConsumeSchema().getModel();
    const promoteConsumeData = await promoteConsumeModel.findOne({ orderId });

    if (promoteConsumeData.consumerStatus === ConsumerStatus.normal) {
        // 撤销消费记录
        promoteConsumeData.consumerStatus = ConsumerStatus.undo;
        await promoteConsumeData.save();

        // 增加金币
        const promoteAccountModel = new PromoteAccountSchema().getModel();
        await promoteAccountModel.findOneAndUpdate({ userId: promoteConsumeData.userId }, { $inc: { coinCount: promoteConsumeData.consumerCount } });
    }

    return 1;
}

// 查询用户账户信息
async function getPromoteAccountByUserId (userId) {
    const promoteAccountModel = new PromoteAccountSchema().getModel();
    let promoteAccountData = await promoteAccountModel.findOne({ userId });
    if (!promoteAccountData) {
        await initPromoteAccount(userId);
        promoteAccountData = await promoteAccountModel.findOne({ userId });
    }
    return promoteAccountData;
}

module.exports = {
    dispatchEnvelope,
    useEnvelop,
    initPromoteAccount,
    bindPromoteRelationship,
    getPromoteQrcode,
    getPromoteOverview,
    generatePromoteIncome,
    getPromoteRecord,
    getPromoteOrderInfo,
    authCustom,
    getPromoteAccountByUserId,
    getEnvelopeById,
    consumeCoin,
    recoverEnvelop,
    recoverCoin,
    recoverPromoteRecord,
    settlementPromoteIncome,
    getPromoteUserInfo,
    changePromote
};
